package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"math/big"

	"github.com/ethereum/go-ethereum/accounts/keystore"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
)

// 节点账户的keystore文件地址和密码
var fromKeyStoreFile string
var password = ""

// http服务地址, 例:http://localhost:8545
var httpUrl = "http://localhost:8001"

// 起始块，结束块
var start, end int64 = 20, 100

//var maxTPS int = 0

var maxTPS int = 380

// var maxTPS int = 714

// var maxTPS int = 952

// var maxTPS int = 1190

// var maxTPS int = 1428

// var maxTPS int = 2380

// var maxTPS int = 2857

// var maxTPS int = 3095

// var maxTPS int = 3571

// var maxTPS int = 4285

// var maxTPS int = 4523

// var maxTPS int = 4761

// var maxTPS int = 5000

// var maxTPS int = 5238

// var maxTPS int = 5952

// var maxTPS int = 6666

// var maxTPS int = 7142

// var maxTPS int = 8333

// var maxTPS int = 9523

// var maxTPS int = 10714

// var maxTPS int = 11904

func main() {
	a := GetTxCountNum()
	GetBlockDifficulty(a)
	// GetNodeAddress()
}

func GetTxCountNum() []int64 {
	client, err := ethclient.Dial(httpUrl)
	if err != nil {
		log.Fatal("dail err=", err)
	}

	// header, err := client.HeaderByNumber(context.Background(), nil)
	// header, err := client.HeaderByNumber(context.Background(), big.NewInt(100))
	// if err != nil {
	// 	log.Fatal(err)
	// }

	// fmt.Println(header.Number.String()) // blockNumber

	// blockNumber := big.NewInt(header.Number.Int64())
	TPS, j := 0, 0
	count1, count2 := 0, 0
	index := make([]int64, end)
	var timestamp [2]uint64
	for i := start; i < start+end; i++ {
		blockNumber := big.NewInt(i)
		block, err := client.BlockByNumber(context.Background(), blockNumber)
		if err != nil {
			log.Fatal("get block err=", err)
		}

		// fmt.Println(block.Number().Uint64()) // 5671744
		// fmt.Println(block.Time().Uint64())       // 1527211625
		// fmt.Println(block.Difficulty().Uint64()) // 3217000136609065
		// fmt.Println(block.Hash().Hex())          // 0x9e8751ebb5069389b855bba72d94902cc385042661498a415979b7b6ee9ba4b9
		temp := len(block.Transactions())
		fmt.Printf("%d ", temp) // txCount
		TPS += temp
		if temp == maxTPS {
			index[j] = i
			j++
			count1 += 1
			// fmt.Println(len(block.Transactions()))
			// fmt.Println(block.Difficulty().Uint64())
		} else {
			count2 += 1
			// fmt.Printf("%d ", len(block.Transactions()))
		}
		// time.Sleep(time.Second)

		if i == start {
			timestamp[0] = block.Time()
		} else if i == start+end-1 {
			timestamp[1] = block.Time()
		}
	}
	fmt.Printf("\nfull=%d, not full=%d\n", count1, count2)
	// fmt.Println(index)
	temp := 0
	for _, v := range index {
		if v != 0 {
			// fmt.Printf("%d,", v)
			temp++
		}
	}
	// fmt.Println()
	a := index[:temp]
	fmt.Println(a)
	// fmt.Println(int64(TPS) / end)
	fmt.Println("Average transaction volume per block")
	fmt.Printf("%.3f\n", float64(TPS)/float64(end))
	fmt.Println(timestamp)
	fmt.Printf("TPS=%.3f\n", (float64(end-1)/float64(end))*float64(TPS)/float64(timestamp[1]-timestamp[0]))

	return a
}

// 函数直接传入切片a
func GetBlockDifficulty(a []int64) {
	client, err := ethclient.Dial(httpUrl)
	if err != nil {
		log.Fatal("dail err=", err)
	}

	count := 0
	fmt.Println("block number with difficulty 1")
	// a := [...]int64{}

	// for i := 0; i < len(a); i++ {
	// 	blockNumber := big.NewInt(a[i])
	// 	block, err := client.BlockByNumber(context.Background(), blockNumber)
	// 	if err != nil {
	// 		log.Fatal("get block err=", err)
	// 	}
	// 	temp := block.Difficulty().Uint64()
	// 	// fmt.Printf("%d ", temp)
	// 	if temp == 1 {
	// 		fmt.Printf("%d ", blockNumber)
	// 		count++
	// 	}
	// }

	for i := start; i < start+end; i++ {
		blockNumber := big.NewInt(i)
		block, err := client.BlockByNumber(context.Background(), blockNumber)
		if err != nil {
			log.Fatal(err)
		}
		temp := block.Difficulty().Uint64()
		// fmt.Printf("%d ", temp)

		if temp == 1 {
			fmt.Printf("%d ", blockNumber)
			count++
		}
	}
	fmt.Printf("\nnoturn=%d\n", count)
}

func GetNodeAddress() {
	str1 := "/home/blochchain/tide/docker/ethereum/node"
	srt2 := "/data/keystore/"
	var str3 string
	var keystorePath string
	var N int

	temp, err := ioutil.ReadFile("/home/blochchain/tide/docker/static-nodes.json")
	if err != nil {
		fmt.Println("get N err=", err)
		return
	}
	for _, v := range temp {
		if v == 61 {
			N++
		}
	}
	// fmt.Println("N =", N)

	N = 21
	for i := 1; i <= N; i++ {
		stri := fmt.Sprintf("%d", i)
		keystorePath = fmt.Sprintf(str1 + stri + srt2)
		// fmt.Println(keystorePath)

		files, err := ioutil.ReadDir(keystorePath)
		if err != nil {
			fmt.Println("get fileDir err=", err)
			return
		}

		for _, f := range files {
			// fmt.Println(f.Name())
			str3 = f.Name()
			// fmt.Println(str3)
			fromKeyStoreFile = fmt.Sprint(keystorePath + str3)
			// fmt.Println(fromKeyStoreFile)

			// 获取私钥方式一，通过keystore文件
			fromKeystore, err := ioutil.ReadFile(fromKeyStoreFile)
			if err != nil {
				fmt.Println("get privateKey err=", err)
				return
			}
			// fmt.Println(string(fromKeystore))
			// require.NoError(t, err)
			fromKey, err := keystore.DecryptKey(fromKeystore, password)
			if err != nil {
				fmt.Println("decryptKey err=", err)
				return
			}
			fromPrivkey := fromKey.PrivateKey
			fromPubkey := fromPrivkey.PublicKey
			fromAddr := crypto.PubkeyToAddress(fromPubkey)
			fmt.Println(fromAddr)
		}
	}
}
